package com.xxxtea.service;

import com.xxxtea.entity.Dish;
import com.xxxtea.entity.Merchant;
import com.xxxtea.entity.Review;
import com.xxxtea.entity.User;
import com.xxxtea.mapper.ReviewMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 评价服务类
 * 
 * 负责评价相关的业务逻辑处理，包括：
 * - 评价信息的查询和管理
 * - 异步计算和更新评分
 * - 更新相关实体的信用分和评分
 * 
 * @author badman
 * @since 1.0.0
 */
@Service
public class ReviewService extends BaseService<ReviewMapper, Review> {
	
	/**
	 * 菜品服务，用于更新菜品评分
	 */
	@Resource
	private DishService dishService;
	
	/**
	 * 用户服务，用于更新用户信用分
	 */
	@Resource
	private UserService userService;
	
	/**
	 * 任务服务，用于获取任务发布者信息
	 */
	@Resource
	private TaskService taskService;
	
	/**
	 * 商家服务，用于更新商家评分
	 */
	@Resource
	private MerchantService merchantService;

	/**
	 * 异步计算并更新评分
	 * 
	 * 根据业务类型计算平均评分，并更新相关实体的评分或信用分：
	 * - 菜品评价：更新菜品评分和商家评分
	 * - 任务评价：更新发布者信用分
	 * 
	 * @param businessId 业务实体ID（菜品ID或任务ID）
	 * @param businessType 业务类型（菜品或任务）
	 */
	@Async
	public void calRating(Integer businessId, Review.BusinessType businessType) {
		// 查询指定业务实体的所有评价，计算平均评分
		double rating = this.lambdaQuery().eq(Review::getBusinessId, businessId)
				.eq(Review::getBusinessType, businessType)
				.list().stream().mapToDouble(Review::getRating)
				.average().orElseThrow(RuntimeException::new);
		
		// 根据业务类型进行不同的评分更新逻辑
		if (businessType == Review.BusinessType.DISH) {
			// 获取菜品信息
			Dish dish = dishService.getById(businessId);
			
			// 更新菜品评分
			dishService.lambdaUpdate().eq(Dish::getId, businessId)
					.set(Dish::getRating, rating)
					.update();

			// 计算并更新商家评分
			// 获取该商家下所有菜品的平均评分
			double avg = dishService.lambdaQuery().eq(Dish::getMerchantId, dish.getMerchantId()).list()
					.stream().mapToDouble(Dish::getRating)
					.average().orElseThrow(RuntimeException::new);
			
			// 更新商家评分
			merchantService.lambdaUpdate().eq(Merchant::getId, dish.getMerchantId())
					.set(Merchant::getRating, avg)
					.update();
		}
		
		if (businessType == Review.BusinessType.TASK) {
			// 获取任务发布者ID
			Integer publisherId = taskService.getById(businessId).getPublisherId();
			
			// 更新发布者信用分
			userService.lambdaUpdate().eq(User::getId, publisherId)
					.set(User::getCreditScore, rating)
					.update();
		}
	}
}